/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.ufpb.halloc.comunicacao;

//import br.ufpb.projetoesa.exceptions.AtualizacaoDeProjetoException;
import br.com.ufpb.halloc.dados.UsuarioDAO;
import br.com.ufpb.halloc.exceptions.AtualizacaoDeTurmaException;
import br.com.ufpb.halloc.exceptions.CursoInexistenteException;
import br.com.ufpb.halloc.exceptions.DisciplinaInexistenteException;
import br.com.ufpb.halloc.exceptions.ProjetoInexistenteException;
import br.com.ufpb.halloc.exceptions.TurmaVaziaException;
import java.util.List;
import br.com.ufpb.halloc.exceptions.AtualizacaoDeProfessorException;
import br.com.ufpb.halloc.exceptions.DisciplinaDuplicadaException;
import br.com.ufpb.halloc.exceptions.DisciplinaInvalidaException;
import br.com.ufpb.halloc.negocio.Centro;
import br.com.ufpb.halloc.negocio.Departamento;
import br.com.ufpb.halloc.negocio.Professor;
import br.com.ufpb.halloc.negocio.Projeto;
import br.com.ufpb.halloc.negocio.Turma;
import br.com.ufpb.halloc.exceptions.TurmaInexistenteException;
import br.com.ufpb.halloc.negocio.Curso;
import br.com.ufpb.halloc.negocio.GerenteDeCadastroTurma;
import br.com.ufpb.halloc.negocio.Disciplina;
import br.com.ufpb.halloc.negocio.GerenteDeCadastroDepartamento;
import br.com.ufpb.halloc.negocio.GerenteDeCadastroProfessor;
import br.com.ufpb.halloc.negocio.Ministra;
import br.com.ufpb.halloc.negocio.Usuario;

/**
 *
 * @author Rennan
 */
public class Facade {
    
    private Departamento dep;
    private Centro centro;
    private static Facade fachada;
    private GerenteDeCadastroProfessor gerenteProfessor;
    private GerenteCadastroDisciplina gerenteDisciplina;
    private GerenteDeCadastroTurma gerenteTurma;
    private GerenteDeCadastroDepartamento gerenteDepartamento;
    private ControleProjeto controleProjeto;
    private ControleCurso controleCurso;
    private UsuarioDAO usuarioDAO;
    
    //Singleton
    public static Facade getInstance(){
        if (fachada == null){
            fachada = new Facade();
            return fachada;
        }
        return fachada;
    }
    
    public Facade(){
        //dep = new Departamento();
        centro = new Centro("CCAE");
        gerenteProfessor = GerenteDeCadastroProfessor.getInstance();
        gerenteDisciplina = GerenteCadastroDisciplina.getInstance();
        gerenteTurma = new GerenteDeCadastroTurma();
        gerenteDepartamento = new GerenteDeCadastroDepartamento();
        controleProjeto = ControleProjeto.getInstance();
        controleCurso = ControleCurso.getInstance();
        usuarioDAO = UsuarioDAO.getInstance();
    }
    
    /**
     * Chama o método do departamento que cadastra um professor.
     * @param _p Professor a ser cadastrado.
     */
    public void cadastraProfessores(Professor _p){
        gerenteProfessor.gravar(_p);
    }

    /**
     * Chama o método de departamento que retora a lista com os professores cadastrados.
     * @return Lista de professores do departamento.
     */
    public List getListaDeProfessores() {
        return gerenteProfessor.buscarTodos();
    }
    
    /**
     * Chama o método de atualização de professor de Departamento.
     * @param profAtual Professor a ser alterado.
     * @param profModificado Professor modificado.
     * @throws AtualizacaoDeProfessorException 
     */
    public void atualizarProfessor(Professor prof) 
            throws AtualizacaoDeProfessorException {
        gerenteProfessor.atualizar(prof);
    }
    //Cadastra Usuario
    public void cadastrarUsuario(Usuario user){
        this.usuarioDAO.cadastrar(user);
    }
    

//    public void atualizarProfessor(Professor p) throws AtualizacaoDeProfessorException{
//        dep.atualizaProfessor(p);
//    }
//
//
//     METODOS QUE USAM A CLASSE DEPARTAMENTO PARA TRATAR PROFESSOR MUDARAM COM O BANCO!
//    
//    
//    /**
//     * Usa o método de Departamento que pesquisa todas as evidências de Professores com o este nome.
//     * @param nome Nome completo ou parcial do Professor.
//     * @return Lista de professores que batem com o String passado.
//     * @throws ProfessorInexistenteException 
//     */
//    public List<Professor> pesquisarEvidenciasDeProfessores(String nome) throws ProfessorInexistenteException{
//        return dep.pesquisaProfessores(nome);
//    }
//
//    public List<Disciplina> pesquisarEvidenciasDeDisciplinas(String nome){
//        return centro.pesquisaDisciplina(nome);
//    }
//
//    public List<Turma> pesquisarEvidenciasDeTurma(String num){
//        return dep.pesquisaTurma(num);
//    }
//
//    /**
//     * Usa o método de Departamento que pesquisa um Professor pelo seu nome e retorna o Professor
//     * se encontrar, caso contrário, lança uma exceção.
//     * @param nome Nome do professor.
//     * @return Professor do departamento.
//     * @throws ProfessorInexistenteException 
//     */
//    public Professor pesquisaProfessorNome(String nome) throws ProfessorInexistenteException{
//        return dep.getProfessorNome(nome);
//    }
//    
//    /**
//     * Pesquisa uma Professor pela sua matrícula e retorna o Professor
//     * se encontrar, caso contrário, lança uma exceção.
//     * @param mat Matrícula do professor.
//     * @return Professor do departamento.
//     * @throws ProfessorInexistenteException 
//     */
//    public Professor pesquisaProfessorMatricula(String mat) throws ProfessorInexistenteException{
//        return dep.getProfessorMat(mat);
//    }
    
    /**
     * Chama o método de departamento que retorna todos os professores cadastrados.
     * @return Lista de Professores cadastrados.
     */
    public List<Professor> getProfessores(){
        return gerenteProfessor.buscarTodos();
    }
    /**
     * Adiciona uma diciplina de interesse a lista do professor usando a matricula dele.
     * @param d
     * @param mat 
     */
//    public void addDiscInteresse (Disciplina d, String mat) throws AtualizacaoDeProfessorException{
//        Professor p = this.buscarProfessorPorMatricula(mat);
//        List<Disciplina> l = p.getDiscInte();
//        l.add(d);
//        p.setDiscInte(l);
//        this.atualizarProfessor(p);
//    }
    
    /**
     * Procura as disciplinas de interesse de um professor pela matricula dele.
     * @param mat 
     */
    public List<Disciplina> getDiscInteresse(String mat){
        Professor p = this.buscarProfessorPorMatricula(mat);
        List<Disciplina> l = p.getDiscInte();
        return l;
    }
    
//// ---> TURMA
//    USO DE DEPARTAMENTO PARA ATIVIDADES COM  TURMA!!!
//    /**
//     * Cadastra uma nova turma no departamento
//     * @param Turma
//     */
//    public void cadastraTurma(Turma turma){
//        dep.addTurma(turma);
//    }
//    
//    /**
//     * Cadastra uma nova turma no departamento
//     * @param identificação da Turma
//     */
//    public void cadastraTurma(String id){
//        dep.addTurma(id);
//    }
//    
//    /**
//     * Cadastra uma nova turma no departamento
//     * @param String id = identificação da Turma
//     * @param int qtdAlunos = quantidade de alunos desta Turma
//     */
//    public void cadastraTurma(String id, int qtdAlunos){
//        dep.addTurma(id, qtdAlunos);
//    }
//    
//    /**
//     * Localiza uma turma pela sua identificação (ID).
//     * @param identificação da Turma
//     * @return Turma
//     * @exception TurmaInexistenteException
//     */
//    public Turma localizaTurmaID(String id) throws TurmaInexistenteException{
//        return dep.getTurmaID(id);
//    }
//    
//    
//    /**
//     * Remove uma Turma pela sua identificação (ID).
//     * @param identificação da Turma
//     * @exception TurmaInexistenteException
//     */
//    public void removerTurmaID(String id) throws TurmaInexistenteException{
//        dep.removerTurma(id);
//    }
//    
//    /**
//     * Remove uma Turma pela sua identificação (ID).
//     * @param Turma
//     * @exception TurmaInexistenteException
//     */
//    public void removerTurmaID(Turma t) throws TurmaInexistenteException{
//        dep.removerTurma(t);
//    }    
//    
//    /**
//     * Verifica se esta Turma esta cadastrada.
//     * @return true se esta Turma estiver cadastrada e false caso contrário.
//     */
//    public boolean isTurmaCadastrada(Turma t){
//        return dep.containsTurma(t);
//    }
//    
//    
//    /**
//     * Retorna todas as turmas já cadastradas
//     * @return Lista com todas as Turmas cadastradas.
//     */
    public List<Turma> getTurmasCadastradas(){
        return null;
    }
//    
//     
//    
//    /**
//     * Remove uma quantidade de alunos da base de dados. A Turma deve ser
//     * identificada antes da remoção através do "id".
//     */
//    public void removerAlunosCadastrados(String id, int qtd) throws TurmaInexistenteException,
//            RemocaoDeAlunosImpossivelException{
//        
//        dep.removerAlunos(id, qtd);
//    }

    /**
     * Adiciona um Projeto a um Professor
     */
    public void cadastrarProjeto(Professor prof, Projeto proj){
        prof.addProjeto(proj);
    }
    
   /*
     * Retorna lista de projetos do professor que contenha parte ou toda a string nome passada 
     * como parametro, no atributo nome do projeto.
     */
   public void pesquisarProjeto(Professor prof, String nome) throws ProjetoInexistenteException{
       prof.pesquisarProjetos(nome);
   }
   
   /*
    * Retorna a lista de projetos de um professor
    */
   public List<Projeto> getProjetos(Professor prof){
       return prof.getProjetos();
   }
   
   /*
    * Retorna o projeto cujo atributo nome é igual a string nome passada por parametro.
    */
   public Projeto getProjeto(Professor p,String nome) throws ProjetoInexistenteException{
       return p.getProjeto(nome);
   }
   
   /*
    * Remove o projeto passado como parametro da lista de projetos do professor.
    */
   public void removerProjeto(Professor p, Projeto proj) throws ProjetoInexistenteException{
       p.removerProjeto(proj);
   }
    
   /*
    * Remove o projeto, cujo o nome é igual a sting passada por parametro, da lista de projetos do professor.
    */
   public void removerProjetoPorNome(Professor p, String nome) throws ProjetoInexistenteException{
       p.removerProjeto(nome);
   }
   
   /*
    * Atualiza o projeto old pelo o projeto niu
    */
   public void atualizarProjeto(Professor p, Projeto old, Projeto niu) throws ProjetoInexistenteException{
       p.atualizarProjeto(old, niu);
   }
    
   
   //METODO QUE USA DEPARTAMENTO PARA ATUALIZAR PROFESSOR!
   /**
     * Remove um Professor da Base de Dados
     */
//    public void removerProfessor(Professor prof){
//        dep.removerProfessor(prof);
//    }
//    
    
   /*
    * Métodos de Projeto
    */
   
   /*
    * Inserir Projeto
    */
   public void inserirProjetoBD(Projeto proj){
       this.controleProjeto.inserir(proj);
   }
   /*
    * Remover Projeto
    */
   public void removerProjetoBD(Projeto proj){
       this.controleProjeto.remover(proj);
   }
   
   /*
    * Remover Projeto pelo ID
    */
   public void removerProjetoPorID(String id){
       this.controleProjeto.removerPorID(id);
   }
   /*
    * Atualizar Projeto
    */
   public void atualizarProjetoBD(Projeto proj){
       this.controleProjeto.atualizar(proj);
   }
   
   /*
    * Pesquisar Por Nome
    */
   public List<Projeto> pesquisarProjetosPorNome(String nome){
       return this.controleProjeto.pesquisarNome(nome);
   }
   /*
    * Pesquisar Por Id
    */
   public Projeto pesquisarProjetoPorId(String id){
       return this.controleProjeto.pesquisarId(id);
   }
   public List<Projeto> getTodosOsProjetosBD(){
       return this.controleProjeto.getProjetos();
   }
   
    // ATENÇÃO! provavelmente os métodos de disciplinas abaixo vai ter que sair!
    
    /**
     * Adiciona uma nova disciplina
     */
    public void addDisciplina(String id, String nome) throws DisciplinaInvalidaException {
        addDisciplina(id, nome, 0);
    }
    
    /**
     * Adiciona uma nova disciplina
     */
    public void addDisciplina(String id, String nome, String ndpto, int creditos) throws DisciplinaInvalidaException {
        centro.addDisciplina(id, nome, ndpto, creditos);
    }
    
    /**
     * Adiciona uma nova disciplina
     */
    public void addDisciplina(String id, String nome, int creditos) throws DisciplinaInvalidaException {
        addDisciplina(id, nome, "", creditos);
    }    
    
    /**
     * Adiciona uma nova disciplina
     * @deprecated 
     */
    public void addDisciplina(String id, String nome, int creditos, int carga) throws DisciplinaInvalidaException {
        //centro.addDisciplina(id, nome, creditos, carga);
        
    }
    
    public List<Disciplina> getDisciplinas(){
        return centro.getDisciplinas();
    }
    
    public List<Professor> buscarProfessoresComProjeto(){
        return gerenteProfessor.buscarTodosComProjeto();
    }
    
//    public void removeDisciplinaDeUmCurso(Curso curso, String id) throws CursoInexistenteException, DisciplinaInexistenteException{
//        centro.removeDisciplinaDeUmCurso(curso, id);
//    }
    
    
    // Novos métodos para disciplinas já com o gerente de disciplinas.
    
    public void salvarDisciplinasArquivoBin(){
        gerenteDisciplina.salvarDisciplinasCadastradasNoArquivoBin();
    }
    
    public void carregarDisciplinasCadastradasNoArquivoBin(){
        gerenteDisciplina.carregarDisciplinasDoArquivoBin();
    }
    
    public void cadastrarDisciplinaNoArquivoBin(Disciplina disc) throws DisciplinaDuplicadaException{
        gerenteDisciplina.cadastraDisciplinaArquivoBin(disc);
    }
    
    public boolean atualizaDisciplinaNoArquivoBin(Disciplina disc) throws DisciplinaInexistenteException{
        return gerenteDisciplina.atualizaDisciplinaArquivoBin(disc);
    }
    
    public boolean removeDisciplinaNoArquivoBin(Disciplina disc) throws DisciplinaInexistenteException{
        return gerenteDisciplina.removeDisciplinaIDAquivoBin(disc);
    }
    
    public Disciplina pesquisaDisciplinaIDNoArquivoBin(String id) throws DisciplinaInexistenteException{
        return gerenteDisciplina.getDisciplinaIDAquivoBin(id);
    }
    
    public List<Disciplina> pesquisaDisciplinaNomeNoArquivoBin(String nome) throws DisciplinaInexistenteException{
        return gerenteDisciplina.getDisciplinaNomeAquivoBin(nome);
    }
    
    public List<Disciplina> getDisciplinasCadastradasNoArquivoBin(){
        return gerenteDisciplina.getDisciplinasArquivoBin();
    }

    public Professor buscarProfessorPorMatricula(String mat) {
       return gerenteProfessor.buscarMat(mat);
    }

    public void removerProfessorMatricula(String mat) {
        gerenteProfessor.apagarMatricula(mat);
    }
    
    // métodos para manipulação de disciplinas no Banco de Dados
    
    public void cadastrarDisciplinaBD(Disciplina disc) throws DisciplinaInvalidaException{
        gerenteDisciplina.cadastraDisciplinaBD(disc);
    }

    public Disciplina pesquisaDisciplinaPorIDNoBD(String id) throws DisciplinaInexistenteException {
        return gerenteDisciplina.pesquisaDisciplinaPorIDNoBD(id);
    }

    public List<Disciplina> pesquisaDisciplinaNomeNoBD(String nome) throws DisciplinaInexistenteException {
        return gerenteDisciplina.pesquisaDisciplinaNomeNoBD(nome);
    }

    public List<Disciplina> getDisciplinasCadastradasNoBD() {
        return gerenteDisciplina.getDisciplinasCadastradasNoBD();
    }
    
    public boolean removerDisciplinaBD (String id) throws DisciplinaInexistenteException{
        return gerenteDisciplina.removerDisciplinaBD(id);
    }
    
    public boolean atualizarDisciplinaBD (Disciplina disc) throws DisciplinaInexistenteException{
        return gerenteDisciplina.atualizaDisciplinaBD(disc);
    }
    //Manipulação de Turma no BD
    
    /**
     * Cadastra uma turma no Banco de dados Postgres
     * @param t 
     */
    public void cadastrarTurmaBD(Turma t){
        gerenteTurma.addTurma(t);
    }
    
    public Turma buscarTurmaBD(String id) throws TurmaInexistenteException{
        return this.gerenteTurma.getTurma(id);
    }
    
    public List<Turma> buscarTurmaNomeBD(String nome) throws TurmaInexistenteException{
        //String n = nome.toLowerCase(); NÃO PRECISOU DISSO!
        return this.gerenteTurma.getTurmaNome(nome);
    }
    
    public void deletarTurmaBD(Turma t) throws TurmaVaziaException, TurmaInexistenteException{
        this.gerenteTurma.removerTurma(t);
    }
    
    public void deletarTurmaBD(String id) throws TurmaInexistenteException, TurmaVaziaException{
        this.gerenteTurma.removerTurma(id);
    }
    
    public void atualizarTurmaBD(Turma t) throws AtualizacaoDeTurmaException{
        this.gerenteTurma.atualizarTurma(t);
    }
    
    public List<Turma> getTodasAsTurmasBD(){
        return this.gerenteTurma.getTurmas();
    }
    
    public int sizeTurmasBD(){
        return this.gerenteTurma.size();
    }
    
    /*
     * Métodos de Curso BD
     */
    
    public void inserirCursoBD(Curso curso) throws CursoInexistenteException{
        this.controleCurso.inserirCursoBD(curso);
    }
    
    public void removerCursoBD(Curso curso){
        this.controleCurso.removerCursoBD(curso);
    }
    
    public void atualizaCursoBD(Curso curso){
        this.controleCurso.atualizarCursoBD(curso);
    }
    
    public Curso pesquisarCursoPorId(String id) throws CursoInexistenteException{
        return this.controleCurso.pesquisarPorIdBD(id);
    }
    
    public List<Curso> pesquisarCursoPorNome(String nome){
        return this.controleCurso.pesquisarPorNomeBD(nome);
    }
    
    public List<Curso> getCursos(){
        return this.controleCurso.getCursos();
    }
    //METODOS DE BANCO DO DEPARTAMENTO
    
    public void cadastrarDepartamentoBD(Departamento d){
        this.gerenteDepartamento.add(d);
    }
    
    public Departamento buscarDepartamentoBD(String id) {
        return this.gerenteDepartamento.getDepartamento(id);
    }
    
    public Departamento buscarDepartamentoBD(Departamento d){
        return this.buscarDepartamentoBD(d);
    }
    
    public void deletarDepartamentoBD(Departamento d) {
        this.gerenteDepartamento.remover(d);
    }
    
    public void deletarDepartamentoBD(String id){
        this.gerenteDepartamento.remover(id);
    }
    
    public void atualizarDepartamentoBD(Departamento d){
        this.gerenteDepartamento.atualizar(d);
    }
    
    public List<Departamento> gettodosOsDepartamentosBD(){
        return this.gerenteDepartamento.todosDepartamentos();
    }
    
    public int sizeDepartamentoBD(){
        return this.gerenteDepartamento.size();
    }
    
    //Preferencias do Professor
    public void inserirPreferencia (String codDisc, String codProf){
        this.gerenteProfessor.inserirPreferencia(codDisc, codProf);
    }
    public List<Disciplina> getDisciplinasDePreferencia(String cod){
        return this.gerenteProfessor.getDisciplinasDePreferencia(cod);
    }
    
    public void alocarDisciplinaAProfessor(String pro, String tur){
        this.gerenteProfessor.alocarDisciplinaAProfessor(pro, tur);
    }
    
     public void desalocarDisciplinaAProfessor(String pro, String tur){
        this.gerenteProfessor.desalocarDisciplinaAProfessor(pro, tur);
    }
    
    public List<Turma> buscarTurmasPreferidas(String codProf){
       return this.gerenteProfessor.turmasPreferidas(codProf);
    }
    
    public List<Turma> turmasAbertas(){
        return this.gerenteTurma.turmasAbertas();
    }
    
    public List<Turma> turmasAlocadas(){
        return this.gerenteTurma.turmasAlocadas();
    }
    
    public List<Turma> turmasAlocadasProfessor(String mat){
        return this.gerenteProfessor.turmasAlocadasProfessor(mat);
    }
    
    public int getQuantidadesDeProjetos(String matricula){
        return this.controleProjeto.getQuantidadeDeProjetos(matricula);
    }
    
    public int numeroDeDisciplinasProfessor(String mat){
        return this.gerenteProfessor.numeroDeDisciplinas(mat);
    }
}
